﻿using System;
using System.Threading;

namespace Common.Threads
{
    public class ThreadHelper : WaitHelper
    {
        private static object lockObj = new object();
        /// <summary>
        /// Thread无返回回调
        /// </summary>
        /// <param name="act"></param>
        /// <param name="callBactAct"></param>
        public static void Callback(Action act, Action callBactAct)
        {
            Thread th = new Thread(new ThreadStart(() =>
            {
                act.Invoke();
                callBactAct.BeginInvoke(null, null);
            }));
            th.Start();
        }
        /// <summary>
        /// Thread可返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public static Func<T> WithReturn<T>(Func<T> func)
        {
            T t = default(T);
            Thread th = new Thread(new ThreadStart(() =>
            {
                t = func.Invoke();
            }));
            th.Start();

            return () =>
            {
                th.Join();
                return t;
            };
        }
        /// <summary>
        /// 回调可返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="act"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static Func<T> Callback<T>(Action act, Func<T> func)
        {
            return WithReturn(() =>
            {
                act.Invoke();
                return func.Invoke();
            });
        }
        /// <summary>
        /// 在指定最大线程数下降方法组进行异步执行,并且可通过ContinueWhenAny/All方法进行线程阻塞
        /// </summary>
        /// <param name="MaxThread">最大线程数,小于等于0时,不进行限制</param>
        /// <param name="acts"></param>
        public override void Wait(int MaxThread, params Action[] acts)
        {
            base.totalQty = acts.Length;
            successQty = 0;

            int invokeThread = 0;
            foreach (Action act in acts)
            {
                act.BeginInvoke((c) =>
                {
                    lock (lockObj)
                    {
                        base.successQty++;
                    }
                }, null);
                //指定最大线程数大于0时,进行当前开启线程数判断
                if (MaxThread > 0)
                {
                    invokeThread++;
                    //正在执行线程大于指定最大线程时,进行线程阻塞
                    while (invokeThread - base.successQty >= MaxThread)
                    {
                        Thread.Sleep(100);
                    }
                }
            }
        }
        public void Wait(params Thread[] ths)
        {
            Wait(0, ths);
        }
        public void Wait(int MaxThread, params Thread[] ths)
        {
            base.totalQty = ths.Length;
            successQty = 0;

            int invokeThread = 0;
            foreach (Thread th in ths)
            {
                new Action(()=>{
                    th.Start();
                    th.Join();
                    lock (lockObj)
                    {
                        base.successQty++;
                    }
                }).BeginInvoke(null,null);
                //指定最大线程数大于0时,进行当前开启线程数判断
                if (MaxThread > 0)
                {
                    invokeThread++;
                    //正在执行线程大于指定最大线程时,进行线程阻塞
                    while (invokeThread - base.successQty >= MaxThread)
                    {
                        Thread.Sleep(100);
                    }
                }
            }
        }
    }
}
